package queryManager;

import general.EvaluatorRaisonner;
import general.EvaluatorSemantic;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.Normalizer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.OWLAnnotation;
import org.semanticweb.owlapi.model.OWLAnnotationProperty;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLDataPropertyExpression;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLObject;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.reasoner.NodeSet;
import org.semanticweb.owlapi.vocab.OWLRDFVocabulary;

import componentManager.Terme;

import utils.GenerateId;

public class SemanticQuery {
	private Query query ;
	private HashMap<String,Double> keyWords;
	private Requete requete;
	private boolean raisonner = false;
	
	
	public SemanticQuery(Query q,HashMap<String, OWLObject> search,String outFilePutPath) throws OWLOntologyCreationException, ClassNotFoundException, InstantiationException, IllegalAccessException{
		this.query = q;
		this.keyWords = new HashMap<String, Double>();
		try {
			this.keyWords = Requete.initKeyWords(query.getText(),GenerateId.ponderationTermeInitial);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		HashMap<String,Double> temp = new HashMap<String, Double>();
		
		for(String s : this.keyWords.keySet()){
			temp.put(s,this.keyWords.get(s));
		}
//		System.out.println("---------------------------------");
//		System.out.println(this.keyWords);
//		System.out.println("****************************");
		for(String s : temp.keySet()){
			//ajouter des mots dans keywords avec une pondération inferieur
			if(!raisonner){
				traitWord(s);
			}
			else{
				traitWordRaisonner(s);
				System.out.println("sss");
			}
		}
		requete = new Requete(this.query,this.keyWords,outFilePutPath);
//		System.out.println(this.keyWords);
//		System.out.println("---------------------------------");
	}
	
	public SemanticQuery(boolean raisonner,Query q,HashMap<String, OWLObject> search,String outFilePutPath) throws OWLOntologyCreationException, ClassNotFoundException, InstantiationException, IllegalAccessException{
		this(q, search, outFilePutPath);
		this.raisonner  = raisonner;
	}
		
	
	//Ajoute des mots dans la requete en utilisant l'ontologie
	public void traitWord(String s) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
		OWLObject oo = null;
		if((oo = EvaluatorSemantic.search.get(s))!=null){
			if(oo instanceof OWLIndividual){
				addIndividualSubClasse(((OWLIndividual)oo).asOWLNamedIndividual());
			}
			else if(oo instanceof OWLClass){
				addSubClasses((OWLClass)oo);
			}
		}
	}
	
	public void traitWordRaisonner(String s){
		OWLObject oo = null;
		if((oo = EvaluatorRaisonner.search.get(s))!=null){
			
			if(oo instanceof OWLIndividual){
				//on ajoute les individu semantiquement lies(range) dans la requete
			}
			else if(oo instanceof OWLClass){
				//on ajoute les instances (+leur range)
			}
		}
	}
	
	/**
	 * Ajoute la classe spécifiée et ses sous classes dans la requete (keywords)
	 * @param class_cour
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws ClassNotFoundException 
	 */
	 public void addSubClasses(OWLClass class_cour) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
	    Set<OWLClassExpression> setClass;
        setClass = class_cour.getSubClasses(EvaluatorSemantic.ont);
        for (OWLAnnotation annotation :  class_cour.getAnnotations(EvaluatorSemantic.ont)){
            if (annotation.getValue() instanceof OWLLiteral) {
                OWLLiteral val = (OWLLiteral) annotation.getValue();
                HashMap<String, Double> temp = Requete.initKeyWords(val.getLiteral(),GenerateId.ponderationTermeAjoute);
                for(String s : temp.keySet()){
                	if(!this.keyWords.containsKey(s))
                		this.keyWords.put(s, temp.get(s));
                }
//                this.keyWords.putAll(Requete.initKeyWords(val.getLiteral(),GenerateId.ponderationTermeAjoute));
            }
        }
        
        for(OWLClassExpression subc : setClass ){
            for (OWLAnnotation annotation :  subc.asOWLClass().getAnnotations(EvaluatorSemantic.ont)){
                if (annotation.getValue() instanceof OWLLiteral) {
                    OWLLiteral val = (OWLLiteral) annotation.getValue();
                    HashMap<String, Double> temp = Requete.initKeyWords(val.getLiteral(),GenerateId.ponderationTermeAjoute);
                    for(String s : temp.keySet()){
                    	if(!this.keyWords.containsKey(s))
                    		this.keyWords.put(s, temp.get(s));
                    }
//                    this.keyWords.putAll(Requete.initKeyWords(val.getLiteral(),GenerateId.ponderationTermeAjoute));
                }
            }
            
            
          //on ajoute les instances de chaque  sous classe 
            for (OWLIndividual o : subc.asOWLClass().getIndividuals(EvaluatorSemantic.ont)) {
    			for (OWLAnnotation annotation : o
    					.asOWLNamedIndividual().getAnnotations(EvaluatorSemantic.ont)) {
    				OWLLiteral val = (OWLLiteral) annotation.getValue();
    				HashMap<String, Double> temp = Requete.initKeyWords(val.getLiteral(),GenerateId.ponderationTermeAjoute);
                    for(String s : temp.keySet()){
                    	if(!this.keyWords.containsKey(s)){
                    		this.keyWords.put(s, temp.get(s));
                    	}
                    }
    			}
    		}
            
            
	    }
        
	}
	 
	//verifier la classe a laquelle une instance appartient
	 /**
	  * Récupère la classe de l'instance spécifiée et l'ajoute ainsi que 
	  * ses sous classes dans la requete (keywords)
	  * @param ind
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws ClassNotFoundException 
	  */
	 public void addIndividualSubClasse(OWLNamedIndividual ind) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
		 for(OWLClassExpression subc : ind.getTypes(EvaluatorSemantic.ont) ){
        	if(!subc.toString().equals("owl:Thing")){ 
        		addSubClasses(subc.asOWLClass());
        	}
        }
	 }
	 
	/**
	 * Recupere les instances d'un classe
	 */
	public void getInstancesByClass(OWLClass c){
		// Ask the reasoner for the instances 
		NodeSet<OWLNamedIndividual> individualsNodeSet = EvaluatorRaisonner.reasoner.getInstances(c, true);
		Set<OWLNamedIndividual> individuals = individualsNodeSet.getFlattened();
		System.out.println("Instances of "+c+": ");
		for (OWLNamedIndividual ind : individuals) {
			System.out.println(" " + ind);
		}
		System.out.println("\n");
	}
	
	/**
	 * Récupère les objects property de l'individu spécifié(domain) et l'individu range associé
	 * @param c
	 */
	public void getObjectProperty(OWLIndividual c){
		// affichage des objects property
		for ( OWLObjectPropertyExpression p : c.getObjectPropertyValues(EvaluatorRaisonner.ont).keySet() ) {
			NodeSet<OWLNamedIndividual> petValuesNodeSet = EvaluatorRaisonner.reasoner.getObjectPropertyValues((OWLNamedIndividual)c,p);
			Set<OWLNamedIndividual> values = petValuesNodeSet.getFlattened();
			System.out.println(p);
			for (OWLNamedIndividual ind : values) {
				System.out.println(" " + ind);
			}
		}
		
	}
	
	/**
	 * Recupère les datas property d'un inividu
	 * @param c
	 */
	public void getDataProperty(OWLIndividual c){
		// affichage des data property
		for ( OWLDataPropertyExpression p : c.getDataPropertyValues(EvaluatorRaisonner.ont).keySet() ) {
			// Now ask the reasoner for the has_pet property values for Mick
			System.out.println(p);
			Set<OWLLiteral> val = EvaluatorRaisonner.reasoner.getDataPropertyValues((OWLNamedIndividual)c,(OWLDataProperty) p);
			for (OWLLiteral o : val) {
				System.out.println(o);
			}
		}
	}
	 
	public Requete getRequete() {
		return requete;
	}


}
